from ctypes import *
import time
import os

current_dir = os.path.dirname(os.path.abspath(__file__))


def check_if_zero(func):
    def wrapper(self, *args, **kwargs):
        self.guide_code = self.guide_test.InitAndConnect(self.ip)
        if self.guide_code == 0:
            func(self, *args, **kwargs)
            return self.guide_test.Disconnect()
        else:
            return 'The main rail connection failed'

    return wrapper


# Determine whether the light guide rail is connected
def check_if_zero_light(func):
    def wrapper(self, *args, **kwargs):
        self.light_code = self.light_test.InitAndConnect(self.light_ip)
        if self.light_code == 0:
            func(self, *args, **kwargs)
            return self.light_test.Disconnect()
        else:
            return 'Light rail connection failed'

    return wrapper


# Check whether the light guide is enabled
def check_if_enabled_light(func):
    def wrapper(self, *args, **kwargs):
        values = c_bool()
        self.light_test.GetAxisEnableState(c_int(args[0]), pointer(values))
        if values.value:
            return func(self, *args, **kwargs)
        return 'Please enable it first'

    return wrapper


# Query zero completion signal
def signal_if_zero_light(func):
    def wrapper(self, *args, **kwargs):
        if args[0] == 4:
            values = c_bool()
            self.light_test.GetBackZeroState(c_int(4), pointer(values))
            if values.value:
                return func(self, *args, **kwargs)
            else:
                self.light_test.SetLeftRotationHome()
                time.sleep(1)
                self.light_test.GetBenchBusyState(c_int(int(4)), pointer(values))
                while values.value:
                    print('Guide rail is moving')
                    time.sleep(1)
                    self.light_test.GetBenchBusyState(c_int(int(4)), pointer(values))
                return func(self, *args, **kwargs)
        if args[0] == 5:
            values = c_bool()
            self.light_test.GetBackZeroState(c_int(5), pointer(values))
            if values.value:
                return func(self, *args, **kwargs)
            else:
                self.light_test.SetRightRotationHome()
                time.sleep(1)
                self.light_test.GetBenchBusyState(c_int(int(5)), pointer(values))
                while values.value:
                    print('Guide rail is moving')
                    time.sleep(1)
                    self.light_test.GetBenchBusyState(c_int(int(5)), pointer(values))
                return func(self, *args, **kwargs)

        return func(self, *args, **kwargs)

    return wrapper


# def check_enabled_light(func):
#     def wrapper(self, *args, **kwargs):
#         print(args[0])
#         # self.light_test.SetAxisEnable(c_int(int(args[0])))
#         if int(args[0]) != 4 and int(args[0]) != 5:
#             code = self.light_test.SetAxisEnable(c_int(int(args[0])))
#             if code == 0:
#                 func(self, *args, **kwargs)
#
#                 self.light_test.StopAxisEnable(c_int(int(args[0])))
#                 return 'Successful move'
#         return func(self, *args, **kwargs)
#
#     return wrapper


# Master track card switch bracket move class
class GtDxoAuto:
    def __init__(self):
        self.guide_test = cdll.LoadLibrary(current_dir + r'/DXOControl-C.dll')
        self.ip = create_string_buffer(b"169.254.232.111")
        self.error = c_ulong(0)
        # Connecting master rail
        # self.guide_code = self.guide_test.InitAndConnect(self.ip)
        # if self.guide_code == 0:
        #     self.heartbeat()
        # else:
        #     self.heart_timer = threading.Timer(5, self.anew_init)
        #     self.heart_timer.start()

    # Reconnect the main rail
    # def anew_init(self):
    #     self.guide_code = self.guide_test.InitAndConnect(self.ip)
    #     if self.guide_code != 0:
    #         print('reconnecting')
    #         self.heart_timer = threading.Timer(5, self.anew_init)
    #         self.heart_timer.start()
    #     else:
    #         self.heartbeat()
    #
    # Master track heartbeat mechanism
    # def heartbeat(self):
    #     current_position = c_double(0)
    #     self.guide_test.GetPosition(c_int(int(0)), byref(current_position))
    #     if current_position.value == 0:
    #         self.guide_code = 1
    #         self.anew_init()
    #     # Create and start the next heartbeat timer
    #     else:
    #         heart_timer_beat = threading.Timer(5, self.heartbeat)  # 每隔5秒触发一次心跳事件
    #         heart_timer_beat.start()

    # Rail movement
    @check_if_zero
    def DominantRailMovement(self, menu, position):
        benchState = c_bool()
        current_position = c_double(0)
        code = self.guide_test.SetBenchMovePosition(c_int(int(menu)), c_double(float(position)))
        if code == 0:
            code_affirm = self.guide_test.StartMoveWithBench(c_int(int(menu)))
            if code_affirm == 0:
                time.sleep(1)
                self.guide_test.GetBenchBusyState(c_int(int(menu)), byref(benchState))
                while benchState.value:
                    print('Guide rail is moving')
                    time.sleep(1)
                    self.guide_test.GetBenchBusyState(c_int(int(menu)), byref(benchState))
                    time.sleep(0.1)
            self.guide_test.GetPosition(c_int(int(menu)), byref(current_position))
            print(current_position)
            if int(current_position.value) == position:
                return 'Successful move'
            return 'Move failure'
        return 'Guide rail input position failed'

    # Other guide rail to work bit
    @check_if_zero
    def Gotimer_2(self):
        self.guide_test.SetTimerWorkPosition_2()
        benchState = c_bool()
        self.guide_test.GetBenchBusyState(c_int(int(5)), byref(benchState))
        print(benchState.value)
        while benchState.value:
            print('Guide rail is moving')
            time.sleep(1)
            self.guide_test.GetBenchBusyState(c_int(int(5)), byref(benchState))
            print('1')
            time.sleep(1)
        print('Successful move')

        return 'Successful move'

    @check_if_zero
    def SetWorkPosition_main(self, menu):
        benchState = c_bool(True)
        self.guide_test.SetBenchMoveVelocity(c_int(menu), c_double(100))
        self.guide_test.SetWorkPosition(c_int(menu))
        time.sleep(1)
        self.guide_test.GetBenchBusyState(c_int(menu), byref(benchState))
        while benchState.value:
            time.sleep(1)
            self.guide_test.GetBenchBusyState(c_int(menu), byref(benchState))
        print('Move complete')
        return 'Move complete'

    # Other guide rails to the docking position
    @check_if_zero
    def SetStopPosition_main(self, menu):
        benchState = c_bool(True)
        self.guide_test.SetBenchMoveVelocity(c_int(menu), c_double(100))
        self.guide_test.SetStopPosition(c_int(int(menu)))
        time.sleep(1)
        self.guide_test.GetBenchBusyState(c_int(menu), byref(benchState))
        while benchState.value:
            time.sleep(1)
            self.guide_test.GetBenchBusyState(c_int(menu), byref(benchState))
        print('Move complete')
        return 'Move complete'

    # Guide speed setting
    @check_if_zero
    def SetSpeed(self, menu, speed):
        code = self.guide_test.SetBenchMoveVelocity(c_int(int(menu)), c_double(float(speed)))
        if code == 0:
            return 'Setting speed succeeded'
        return 'Failed to set speed'

    # Chart switching
    @check_if_zero
    def ChartSwitching(self, location):
        code = self.guide_test.SwitchImageCard(c_int(int(location)), byref(self.error))
        cardState = c_bool(True)
        cardId = c_int(0)
        time.sleep(1)
        if code == 0:
            self.guide_test.GetImageCardBusyState(byref(cardState))
            while cardState.value:
                print('chart is switching')
                time.sleep(1)
                self.guide_test.GetImageCardBusyState(byref(cardState))
            self.guide_test.GetCurrentImageCardId(byref(cardId))
            print('图卡切换成功')
            if cardId.value == int(location):
                return 'The picture card is switched successfully'
        return 'Failed to switch the picture card'

    # Chart back to warehouse
    @check_if_zero
    def ChartGoHome(self):
        code = self.guide_test.SetImageCardGoHome()
        print(code)
        cardState = c_bool(False)
        cardId = c_int(0)
        time.sleep(1)
        if code == 0:
            self.guide_test.GetImageCardBusyState(byref(cardState))
            while cardState.value:
                print('chart is switching')
                time.sleep(1)
                self.guide_test.GetImageCardBusyState(byref(cardState))
            self.guide_test.GetCurrentImageCardId(byref(cardId))
            if cardId.value == 0:
                return 'Chart returned successfully'
        return 'Chart failed to return to warehouse'


# Light guide class
class GtLightAuto:
    def __init__(self):
        self.light_test = cdll.LoadLibrary(current_dir + r'/DXOALSControl-C.dll')
        self.light_ip = create_string_buffer(b'169.254.232.112')

    @check_if_zero_light
    def ddd(self):
        time.sleep(1)
        self.light_test.SetAxisEnable(c_int(1))
        time.sleep(1)
        self.light_test.SetAxisEnable(c_int(2))
        time.sleep(1)
        self.light_test.SetAxisEnable(c_int(3))
        time.sleep(1)
        self.light_test.SetAxisEnable(c_int(0))

        # if self.light_code == 0:
        #     self.LightHeartBeat()
        # else:
        #     self.heart_timer_light = threading.Timer(5, self.light_anew_init)
        #     self.heart_timer_light.start()

    # Reconnect the light rail
    # def light_anew_init(self):
    #     self.light_code = self.light_test.InitAndConnect(self.light_ip)
    #     if self.light_code != 0:
    #         print('Light rail reconnecting')
    #         self.heart_timer_light = threading.Timer(5, self.light_anew_init)
    #         self.heart_timer_light.start()
    #     else:
    #         self.LightHeartBeat()
    #
    # # Light rail heartbeat mechanism
    # def LightHeartBeat(self):
    #     pValue = c_float(0)
    #     self.light_test.GetMoveSpeed(c_int(1), byref(pValue))
    #     if pValue.value == 0:
    #         self.light_code = 1
    #         self.light_anew_init()
    #     else:
    #         heart_timer_beat_light = threading.Timer(5, self.LightHeartBeat)  # 每隔5秒触发一次心跳事件
    #         heart_timer_beat_light.start()

    # Moving light guide
    @check_if_zero_light
    # @check_enabled_light
    @signal_if_zero_light
    def MovingLightGuide(self, menu, position):
        code = self.light_test.SetBenchMovePosition(c_int(int(menu)), c_double(float(position)))
        if code == 0:
            values = c_bool()
            pValue = c_float()
            code_affirm = self.light_test.StartMoveWithBench(c_int(int(menu)))
            time.sleep(1)
            if code_affirm == 0:
                self.light_test.GetBenchBusyState(c_int(int(menu)), pointer(values))
                while values.value:
                    print('Guide rail is moving')
                    time.sleep(1)
                    self.light_test.GetBenchBusyState(c_int(int(menu)), pointer(values))
            self.light_test.GetPosition(c_int(menu), byref(pValue))
            print(pValue.value)
            if pValue.value == position:
                return 'Moving light successful'
        return 'Moving light failure'

    # Set the light rail speed
    # @check_if_zero_light
    def SetLightRailSpeed(self, menu, speed):
        code = self.light_test.SetBenchMoveVelocity(c_int(int(menu)), c_double(float(speed)))
        if code == 0:
            code_sure = self.light_test.SetBenchMoveVelocitySure(c_int(int(menu)))
            if code_sure == 0:
                return 'Setting speed succeeded'
        return 'Failed to set speed'


GtMainAuto = GtDxoAuto()
GtAlsAuto = GtLightAuto()
if __name__ == '__main__':
    # print(GtMainAuto.ChartSwitching(3))
    print(GtAlsAuto.ddd())
    # GtMainAuto.ChartGoHome()+
    # while True:
    #     for i in range(1,11):
    #         time.sleep(1)
    #         print(GtMainAuto.ChartSwitching(i))
    # # print(GtAlsAuto.MovingLightGuide(6, 0))
    # GtMainAuto.ChartGoHome()
    # print(GtMainAuto.ChartSwitching(4))
